﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Moon.Sql
{
    public class SqlServerUpdateable<T> : UpdateableProvide<T>
    {
        public SqlServerUpdateable(IDatabase _Database)
            : base(_Database) { }

        public override SqlBuilderResult ToSql()
        {
            SqlBuilderResult sqlResult = GetSqlParam();
            string sql = "update {3} set {1} from {0} {3} where {2}";
            if (_Limit.HasValue)
            {
                sql = "update top (" + _Limit + ") {3} set {1} from {0} {3} where {2}";
            }
            return new SqlBuilderResult()
            {
                Sql = string.Format(sql, IsQuote ? Database.SqlDialect.SetSqlName(MasterTableName) : MasterTableName,
                    sqlResult.Sql, _Where.Sql, CommonUtils.TableAliasName),
                DynamicParameters = sqlResult.DynamicParameters
            };
        }

        public override int BulkUpdate<TempTable>(List<TempTable> updateList)
        {
            if (Columns == null || Columns.Count == 0)
            {
                throw new Exception("there are no updated columns");
            }
            if (updateList == null || updateList.Count == 0)
            {
                throw new Exception("save object is empty");
            }
            if (!MasterTable.Properties.Any(i => i.IsPrimaryKey) && UpdateWhereColumns.Count == 0)
            {
                throw new Exception("update column conditions or primary key is empty");
            }
            if (Database.Transaction == null)
                throw new Exception("transaction not opened");
            string script = new SqlServerCodeFirst(Database).Build<TempTable>();
            script = script.Substring(script.IndexOf('('));
            string tempTableName = $"#t_moon_{Guid.NewGuid().ToString("N")}";
            //创建临时表
            string sql = $"create table {tempTableName}{script}";
            Database.Execute(sql);
            //插入临时表
            InsertableProvide<TempTable> insertable = new SqlServerInsertable<TempTable>(Database);
            insertable.Insertable(updateList).TableName(tempTableName).BulkInsert();
            sql = $@"update t2 set {UpdateSetColumns()} 
            from {tempTableName} t1 
            inner join {Database.SqlDialect.SetSqlName(MasterTableName)} t2 on {UpdateSetWhere()}";
            return Database.Execute(sql);
        }

        public override async Task<int> BulkUpdateAsync<TempTable>(List<TempTable> updateList)
        {
            int result = BulkUpdate(updateList);
            return await Task.FromResult(result);
        }
    }
}
